﻿namespace Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Entities;
    using DAL;
    using System.ComponentModel.Composition;

    [Export(typeof(IDetailsService))]
    public class DetailsService : BaseReportingService, IDetailsService
    {
        #region Member Variables

        protected readonly IAuditedOperationRepository _auditedOperationRepository;

        #endregion

        #region Constructor

        [ImportingConstructor]
        public DetailsService(IAuditedOperationRepository auditedOperationRepository)
        {
            this._auditedOperationRepository = auditedOperationRepository;
        }

        #endregion

        #region IDetailsService

        IEnumerable<AuditedOperation> IDetailsService.GetAllFileActions(string fileName)
        {
            return _auditedOperationRepository.Find(o => o.ObjectName == fileName);
        }

        UserDetails IDetailsService.GetAllUserActions(string userName)
        {
            IEnumerable<AuditedOperation> userOperations = _auditedOperationRepository.Find(o => o.UserAccount == userName);
            return GetUserDetails(userOperations);
        }

        IEnumerable<AuditedOperation> IDetailsService.SearchFileActions(string fileName, FilterOperations filter)
        {
            var operations = from o in _auditedOperationRepository.Context.AuditedOperations
                             where o.ObjectName == fileName
                             select o;

            return FilterOperations(filter, operations);
        }

        UserDetails IDetailsService.SearchUserActions(string userName, FilterOperations filter)
        {
            var userOperations = from o in _auditedOperationRepository.Context.AuditedOperations
                                 where o.UserAccount == userName
                                 select o;

            IEnumerable<AuditedOperation> filteredOperations = FilterOperations(filter, userOperations);

            return GetUserDetails(filteredOperations);
        }

        #endregion

        #region Private Methods

        private int GetOeprationsCount(IEnumerable<AuditedOperation> filteredOperations, OperationType operationType)
        {
            return filteredOperations.Where(au => au.OperationType == (int)operationType).Count();
        }

        private IEnumerable<UsersMachines> GetUsersMachines(IEnumerable<AuditedOperation> filteredOperations)
        {
            var usersMachines = from operation in filteredOperations
                                group operation by operation.ClientMachineName into g
                                select new UsersMachines { MachineName = g.Key, OperationsCount = g.Count() };
            return usersMachines.Take(5);
        }

        private UserDetails GetUserDetails(IEnumerable<AuditedOperation> filteredOperations)
        {
            var userDetails = new UserDetails();
            userDetails.LastActivityDate = filteredOperations.Max(f => f.ReceivedTime);

            userDetails.CreatedCount = GetOeprationsCount(filteredOperations, OperationType.Create);
            userDetails.DeletedCount = GetOeprationsCount(filteredOperations, OperationType.Deleted);
            userDetails.MovedCount = GetOeprationsCount(filteredOperations, OperationType.Move);
            userDetails.RenamedCount = GetOeprationsCount(filteredOperations, OperationType.Rename);
            userDetails.DeletedDirectoriesCount = GetOeprationsCount(filteredOperations, OperationType.DeleteDirectory);
            userDetails.CreatedDirectoriesCount = GetOeprationsCount(filteredOperations, OperationType.CreateDirectory);
            userDetails.RenamedDirectoriesCount = GetOeprationsCount(filteredOperations, OperationType.RenameDirectory);
            userDetails.PermissionChangedCount = GetOeprationsCount(filteredOperations, OperationType.PermissionChange);
            userDetails.OwnerChangedCount = GetOeprationsCount(filteredOperations, OperationType.OwnerChange);
            userDetails.TotalOperationsCount = filteredOperations.Count();
            userDetails.UsedMachines = GetUsersMachines(filteredOperations);
            userDetails.ChangedCount = userDetails.DeletedCount + userDetails.RenamedCount + GetOeprationsCount(filteredOperations, OperationType.Write);

            return userDetails;
        }

        #endregion
    }
}